Net.h++ is a new C++ class library from Rogue Wave Software that offers:
Net.h++'s elegantly designed three-tiered architecture gives you flexibility and power. You can write code to a specific protocol (such as TCP/IP) using the Communication Adapter Layer, or to a generic Portal Layer that interfaces with a variety of protocols. The Communication Services Layer also gives you options for how you move data into and out of portals. Each layer is built on the one before, and offers increasingly abstract services. All three layers are built on a foundation of fundamental datatypes. Here's how it works:
Because most compilers shipping today lack the string and container classes needed to build a sophisticated product like Net.h++, we have included them as part of the Foundation Layer. The Foundation Layer also includes a set of additional services that are used by the other three layers. In addition to making the interface easier to use and understand, the Foundation Layer simplifies the implementation of Net.h++.
The Foundation Layer also provides Net.h++ with the ability to use multithread-safe system facilities and to enforce internal locking to maintain its own internal integrity. When compiled with your compiler's multithread-safe option, Net.h++ code is multithread-safe.
The Foundation Library is comprised of Net.h++ classes and the fundamental data structures and collections found in Tools.h++, the popular C++ foundation class library. As the new language standard for C++ is implemented by compiler vendors, Tools.h++ is slated to become the object-oriented interface to the new standard library. Because Net.h++ is built on Tools.h++, you can be confident that you'll have a migration path in the future to the new standard, and to added enhancements such as compatibility with new multithreading and distributed environments
The Communication Adapter Layer includes separate C++ modules that encapsulate familiar network communication 'C' APIs with an easy to use, object-oriented C++ interface. All of the flexibility of the underlying 'C' API is provided without sacrificing the power and expressiveness of C++. Net.h++ even provides "kick downs", allowing you to interleave legacy 'C' code with Net.h++ code. At this level of abstraction, you have fine control over the features of a specific protocol.
Net.h++ currently encapsulates the de facto standard TCP/IP interface-the Berkeley sockets API. The Net.h++ sockets module uses the same concepts found in the underlying 'C' API, including sockets, socket addresses, and Internet hosts, but with an intuitive, object-oriented interface. It leverages the most powerful features of C++, including exception handling and templates, without sacrificing any of the sockets functionality. If you've used sockets in the past, mastering the Net.h++ Berkeley sockets module is a breeze.
Future releases of Net.h++ will include C++ modules for other network communication services, such as the System V Transport Layer Protocol (TLI) and Pipes.
Turn to the Portal Layer when you need to write code that's portable to other network protocols. The Portal Layer sits on top of the Communication Adapter Layer, providing a single interface to multiple platforms, network services and protocols. The same Portal Layer code can talk to any of the underlying Communication Adapter modules, simplifying development and ensuring portability. As additional Adapter modules become available, you'll be able to easily adapt existing Net.h++ applications to work with other network communication services. Simply plug the new adapter module into the Portal Layer, and it's ready to go.
The Portal Layer provides a single, channel-independent portal class, called RWPortal, that encapsulates the communication details of each Adapter module. Use RWPortal for applications that use different connection types without needing to write application code specific to any one. The Portal Layer hides the details of the underlying Adapter module and API, simplifying your programming task and making your code easier to read.
The Communication Services Layer offers modules that provide transport-independent communication services. Net.h++ currently includes the IOStream module, which connects to the Portal Layer and provides an efficient, type-safe, C++ communication mechanism. This module allows for communication into and out of a portal using the standard C++ iostream classes and the Rogue Wave virtual streams classes, which were developed to overcome the limitations of the C++ iostream classes.
With the virtual streams classes, you can both use and write streaming operators without knowing anything about the final output medium or formatting to be used. For example, the output medium could be a disk, memory allocation, or even a network. The formatting could be binary, ASCII, or network packet. Because of this, the virtual stream classes provide a very powerful persistence mechanism for Net.h++ applications. As an added bonus, if you've already built objects that use the Tools.h++ virtual streams persistence technology, you can seamlessly pass them across the network using Net.h++'s IOStreams module.
As stated earlier, Net.h++ significantly simplifies network programming. The following examples illustrate this point.
This example shows client side code for interaction with a "Greeting" server that will return the greeting that was sent to it from the previous connection. To be fair, we simplified the Berkeley socket's code greatly by using Rogue Wave's RWCString from Tools.h++ (Since everyone already has a copy -- right?). Without the use of RWCString, the Berkeley sockets example would be even uglier!
================ Net.h++ client code ================
#include <iostream.h> #include <rw/net/sockport.h> #include <rw/net/inetaddr.h> main(int argc, char **argv) { RWCString greeting; cout << "Type in a greeting: " << flush; greeting.readLine(cin); try { RWSocketPortal port( RWInetAddr(3010,"cold.roguewave.com") ); port.sendAtLeast( greeting ); RWCString incoming; while ( !(incoming=sock.recv()).isNull() ) { cout << incoming << flush; } } catch (const RWxmsg& x) { cerr << "Error: " << x.why() << endl; } return 0; }
================ BSD-sockets client code ================
#include <iostream.h> #include <stdlib.h> #include <errno.h> #include <unistd.h> /* looking for read */ #include <string.h> /* looking for strlen */ #include <sys/types.h> /* network includes */ #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> /* gethostbyname() */ #include <rw/cstring.h> const int AL_BUFSIZE = 512; // a small buffer, so it'll fit on the stack int main(int argc, char **argv) { RWCString greeting; cout << "Type in a greeting: " << flush; greeting.readLine(cin); // Set up address structure for host connection struct hostent *h = gethostbyname("cold.roguewave.com"); if (h==0) { cerr << "Error: Can't find host\n"; exit(1); } struct in_addr hostaddr = *(struct in_addr*)*h->h_addr_list; struct sockaddr_in addr; memset((void*)&addr, 0, sizeof(sockaddr)); // unused bytes must be zero addr.sin_family = AF_INET; addr.sin_port = htons(3010); addr.sin_addr = *(struct in_addr*)*h->h_addr_list; // Connect socket to address int sock = socket(PF_INET,SOCK_STREAM,0); if (sock<0) { cerr << "Error: failed to create socket\n"; exit(1); } if ( connect(sock,(sockaddr*)&addr,sizeof(addr)) != 0 ) { cerr << "Error: failed to connect - error " << errno << endl; exit(1); } // Send message to the socket while (!greeting.isNull()) { int n = write(sock,greeting.data(),greeting.length()); if (n>0) { greeting.remove(0,n); } else { cerr << "Failure writing to connection" << endl; exit(1); } } // Hear what the socket has to say char buf[AL_BUFSIZE+1]; int n; while((n=read(sock,&buf,AL_BUFSIZE))>0) { buf[n] = '\0'; cout << buf << flush; } return 0; }
================ Net.h++ server code ================
#include <rw/net/sockport.h> #include <rw/net/portstrm.h> #include <rw/net/inetaddr.h> static RWCString lastGreeting = "It's my first time. Honest"; main() { RWSocketListener listener( RWInetAddr(3010) ); for (;;) { RWPortal portal = listener(); // get the next incoming connection RWPortalIStream strm(portal); portal.sendAtLeast(lastGreeting); // send previous greeting lastGreeting.readLine(strm); // read this client's greeting } return 0; }
The Net.h++ package includes a number of tutorials and example programs that demonstrate how to use and extend the Net.h++ library. In particular, we've included a tutorial that extends the Net.h++ Communication Services Layer to include a Reactor Service Module. This module provides a code framework for building asynchronous network servers. To use this tutorial code, all you need to do is provide the server functionality. The framework handles synchronizing I/O, accepting connections, instantiating servers, and other tedious, error-prone details. Studying this tutorial is an excellent way to come up to speed on Net.h++, with the added bonus that you get some useful, well-written code.
Net.h++ 1.0 includes support for Berkeley Sockets on Windows 3.1, Windows NT, Solaris, SunOS, and HP/UX. Additional network services will be added in future releases. Tools.h++ is required for use of Net.h++.